package com.china.produce.controller;

import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 *
 * @ClassName
 * @Author niujie
 * @Version
 * @Description
 * @CreateTime 2022/2/16
 */
@RequestMapping("/async")
@RestController
public class AsyncController {

    @Autowired
    @Qualifier("THREAD_POOL")
    private ThreadPoolTaskExecutor executor;

    private volatile boolean stop = true;

    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /**
     * 测试AopContext.currentProxy()
     */
    @PostMapping("/testAsync")
    public void testAsync()
    {
        System.out.println("thread name: " + Thread.currentThread().getName() + " start: " +  LocalDateTime.now().format(formatter));

        AsyncController proxy = (AsyncController) AopContext.currentProxy();

        proxy.exec();

        System.out.println("thread name: " + Thread.currentThread().getName() + " end: " + LocalDateTime.now().format(formatter));
    }

    /**
     * 同一个类中调用异步方法生效，必须定义
     * enableAsync中导入了AsyncAnnotationBeanPostProcessor
     * 在AsyncAnnotationBeanPostProcessor中添加advisor AnnotationAsyncExecutionInterceptor
     * 请求方法在执行的时候，因为是cglib代理对象的调用，所以执行了CglibAopProxy.interceptor()
     * List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
     * 获取拦截器链路时候，获得初始化添加的AnnotationAsyncExecutionInterceptor advisor 执行invoke()方法
     * ****AsyncExecutionInterceptor***
     * 获取执行的线程池，不添加默认
     *
     * AsyncProxyDefinitionRegistryPostProcessor
     */
    @Async
    public void exec()
    {
        try {
            TimeUnit.SECONDS.sleep(10);
        }catch (Exception exception) {
        }
        System.out.println(Thread.currentThread().getName() + "====" + LocalDateTime.now().format(formatter));
    }

    @PostMapping("/threadRunTask")
    public void threadRunTask() {

        AsyncController proxy = (AsyncController) AopContext.currentProxy();

        proxy.runThread();
    }

    /**
     * 指定线程分批跑任务
     */
    @Async
    public void runThread() {
        AtomicInteger page = new AtomicInteger(1);

        while (stop) {
            executor.execute(() -> {
                int pages = page.get();
                if (Thread.currentThread().getName().contains("THREAD_POOL_PREFIX")) {
                    page.incrementAndGet();
                    try {
                        TimeUnit.SECONDS.sleep(1);
                        if (pages > 20) {
                            stop = false;
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }
}
